package src;

import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Console {

    int columnNumber;//列数
    int lineNumber;//行数
    private FirstPage firstPage;//第一页
    private SecondPage view;//主要界面
    private SimplexMethod arthmetic;//单纯形法算法

    private CommonFraction[][] Coefficient_A;//技术系数A
    private CommonFraction[] Coefficient_B;//限额系数B
    private CommonFraction[] Coefficient_C;//价值系数C
    private boolean isUnconstrainedVariable[];//每个变量是否为非约束变量
    private String isEquality[];//每一列的符号（大于小于等于）情况
    private boolean isEnd = false;//是否结束
    private CommonFraction[] optimalSolution;//最优值
    private boolean isMax = true;//是否求最大值
    private CommonFraction[] checkingNumbers;//检验数
    private CommonFraction[] coefficient_theta;//θ
    private SimplexTableau newSimplexTableau;//单纯形表
    private int positionOfBasicVariable[];//基变量对应角标
    private ThirdPage operationInterface;//计算界面

    //先通过首页启动程序，再让首页启动算法
    Console(){
        this.operationInterface = new ThirdPage();
        firstPage = new FirstPage(true);
        firstPage.confirm.addMouseListener(new MouseProcess1());
    }
    public void ProcesInFirstPage() {

        //判断输入的是否是数字
        if(firstPage.columnNumber.getText().equals("") || firstPage.lineNumber.getText().equals("")) {
            JOptionPane.showMessageDialog(firstPage, "数字都还没输全呢，干啥呢？", "提醒你字没输全" ,JOptionPane.ERROR_MESSAGE);
            return;
        }
        //检测输入是否正常
        if(!checkIsNumber(firstPage.columnNumber.getText()) || !checkIsNumber(firstPage.lineNumber.getText()) ) {
            JOptionPane.showMessageDialog(firstPage, "叫你输数字或者分数，干啥呢？", "输入字符非法" ,JOptionPane.ERROR_MESSAGE);
            return;
        }

        columnNumber = (int)(new CommonFraction(firstPage.columnNumber.getText()).getDecimalNumber());
        lineNumber = (int)(new CommonFraction(firstPage.lineNumber.getText()).getDecimalNumber());
//        coefficient_theta = new CommonFraction[lineNumber];


        //判断行列长度是否在合理区间
        //稳中带皮的防错机制
        if(columnNumber <= 0 && lineNumber <= 0) {
            JOptionPane.showMessageDialog(firstPage, "行列数都太小啦！故意输"+lineNumber+"和"+columnNumber+"玩我吗？", "列数过小" ,JOptionPane.WARNING_MESSAGE);
            return;
        }
        if(lineNumber <= 0) {
            JOptionPane.showMessageDialog(firstPage, "行数太小啦！故意输"+lineNumber+"玩我吗？", "行数过小" ,JOptionPane.WARNING_MESSAGE);
            return;
        }
        if(lineNumber > 18) {
            JOptionPane.showMessageDialog(firstPage, "行数太大啦，由于界面设计的原因最多只支持18行", "行数过大" ,JOptionPane.WARNING_MESSAGE);
            return;
        }
        if(columnNumber <= 0) {
            JOptionPane.showMessageDialog(firstPage, "列数太小啦！故意输"+columnNumber+"玩我吗？", "列数过小" ,JOptionPane.WARNING_MESSAGE);
            return;
        }
        if(columnNumber > 16) {
            JOptionPane.showMessageDialog(firstPage, "列数太大啦，由于界面设计的原因最多只支持16列", "列数过大" ,JOptionPane.WARNING_MESSAGE);
            return;
        }


        firstPage.setVisible(false);
        firstPage.columnNumber.setText("");
        firstPage.lineNumber.setText("");
        view = new SecondPage(lineNumber, columnNumber);
        view.nextStep.addMouseListener(new MouseProcess2());
    }


    //开始计算
    public void start(){
        coefficient_theta = new CommonFraction[lineNumber];
        Coefficient_A = new CommonFraction[lineNumber][columnNumber];
        Coefficient_B = new CommonFraction[lineNumber];
        Coefficient_C = new CommonFraction[columnNumber];
        isEquality = new String[lineNumber];
        isUnconstrainedVariable = new boolean[columnNumber];
        if(view.maxOrMin.getSelectedItem() == "MAX") {
            isMax = true;
        }
        else {
            isMax = false;
        }

        for(int i=0; i<lineNumber; i++) {


            String strB = view.textOfCoefficient_B[i].getText();
            //检测输入是否正常
            if(checkIsNullString(strB)) {
                JOptionPane.showMessageDialog(null, "叫你输东西，干啥呢？", "字都还没输呢", JOptionPane.ERROR_MESSAGE);
                return;
            }
            else if(!checkIsStringOfCommonFraction(strB)) {
                JOptionPane.showMessageDialog(null, "叫你输数字或者分数进去，干啥呢？", "输入字符非法", JOptionPane.ERROR_MESSAGE);
                return;
            }
            Coefficient_B[i] = new CommonFraction(strB);
            isEquality[i] = (String)view.optionsOfSymbols[i].getSelectedItem();


            for(int j=0; j<columnNumber; j++) {
                //检测输入是否正常
                String strA = view.textOfMatrixA[i][j].getText();
                if(checkIsNullString(strA)) {
                    JOptionPane.showMessageDialog(null, "叫你输东西，干啥呢？", "字都还没输呢", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                else if(!checkIsStringOfCommonFraction(strA)) {
                    JOptionPane.showMessageDialog(null, "叫你输数字或者分数进去，干啥呢？", "输入字符非法", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                Coefficient_A[i][j] = new CommonFraction(strA);
            }
        }

        for(int j=0; j<columnNumber; j++) {
            if(view.optionsOfUnconstrainedVariable[j].getSelectedItem() == "是") {
                this.isUnconstrainedVariable[j] = true;
            }
            else{
                this.isUnconstrainedVariable[j] = false;
            }


            //检测输入是否正常
            String strC = view.textOfCoefficient_C[j].getText();
            if(checkIsNullString(strC)) {
                JOptionPane.showMessageDialog(null, "叫你输东西，干啥呢？", "字都还没输呢", JOptionPane.ERROR_MESSAGE);
                return;
            }
            else if(!checkIsStringOfCommonFraction(strC)) {
                JOptionPane.showMessageDialog(null, "叫你输数字或者分数进去，干啥呢？", "输入字符非法", JOptionPane.ERROR_MESSAGE);
                return;
            }
            Coefficient_C[j] = new CommonFraction(strC);
        }

        SimplexMethod arithmetic = new SimplexMethod(Coefficient_A, Coefficient_B, Coefficient_C, isUnconstrainedVariable, isEquality, isMax);
        this.arthmetic = arithmetic;
        arithmetic.initialize();
        int time = 0;//防止出现无限迭代的情况
        while(true) {
            if(time >50) {
                JOptionPane.showMessageDialog(null, "迭代时间太长,强行终止,可能是因为大M法的M我设的太大了。请联系QQ740597991 王勾勾", "程序错误" ,JOptionPane.WARNING_MESSAGE);
                isEnd = true;
                break;
            }
            time++;
            arithmetic.judge();
            if(arithmetic.result != "" && !arthmetic.result.equals("无界解")){
                for(int i=0; i<lineNumber; i++) {
                    arithmetic.coefficient_theta[i] = null;
                }
            }
            transmitToTable();
            transmitToView();
            arithmetic.matrixAB.printMatrix();
            if(arithmetic.result != "") {
                this.newSimplexTableau.labelOfStatus.setText(arithmetic.result);
                isEnd = true;
                System.out.println(arithmetic.result);
                if(arithmetic.result.equals("有唯一最优解")) {
                    this.optimalSolution = new CommonFraction[arithmetic.optimalSolution.length];
                    this.optimalSolution = arithmetic.optimalSolution;
                    String solution = "最";
                    if(arithmetic.isMax) {
                        solution += "大值为:";
                    }
                    else {
                        solution += "小值为:";
                    }
                    solution += arithmetic.optimalValue.getCommonFraction();
                    this.newSimplexTableau.labelOfOptimalValue.setText(solution);
                    String result = "(";
                    for(int i=0; i<arithmetic.optimalSolution.length; i++) {
                        result += arithmetic.optimalSolution[i].getCommonFraction();
                        if(i != arithmetic.optimalSolution.length-1) {
                            result += ", ";
                        }
                    }
                    result += ")";
                    this.newSimplexTableau.labelOfOptimalSoluttions.setText("最优解为:"+result);
                    for(CommonFraction cf :arithmetic.optimalSolution) {

                        System.out.println(cf + " ");
                    }
                    System.out.println();
                    System.out.println("最优解是:"+arithmetic.optimalValue);
                }
                break;
            }
            else {
                System.out.println("迭代中");
                arithmetic.iteration();
            }
        }

    }



    class MouseProcess1 implements MouseListener{

        @Override
        public void mouseClicked(MouseEvent arg0) {
            ProcesInFirstPage();
        }

        @Override
        public void mouseEntered(MouseEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseExited(MouseEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseReleased(MouseEvent arg0) {
            // TODO Auto-generated method stub

        }

    }



    class MouseProcess2 implements MouseListener{

        @Override
        public void mouseClicked(MouseEvent e) {
//            isEnd = false;
            if(!isEnd) {
                start();
            }
            else{
                JOptionPane.showMessageDialog(null, "计算已结束", "提示", JOptionPane.ERROR_MESSAGE);
            }
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }

    }


    private void transmitToTable(){
        this.lineNumber = arthmetic.matrixAB.matrix.length;
        this.columnNumber = arthmetic.matrixAB.matrix.length - 1;

        this.Coefficient_A = new CommonFraction[this.lineNumber][this.columnNumber];
        this.Coefficient_A = arthmetic.getA().matrix;
        this.Coefficient_B = new CommonFraction[this.lineNumber];
        for(int i=0; i<lineNumber; i++) {
            this.Coefficient_B[i] = arthmetic.getB().matrix[i][0];
        }
        this.Coefficient_C = new CommonFraction[this.columnNumber];
        this.Coefficient_C = arthmetic.coefficient_C;
        this.checkingNumbers = new CommonFraction[this.columnNumber];
        this.checkingNumbers = arthmetic.checkingNumbers;
        this.coefficient_theta = new CommonFraction[this.lineNumber];
        this.coefficient_theta = arthmetic.coefficient_theta;
        this.positionOfBasicVariable = new int[this.lineNumber];
        this.positionOfBasicVariable = arthmetic.positionsOfBasicVariable;

    }

    private void transmitToView(){
        this.newSimplexTableau = new SimplexTableau(this.positionOfBasicVariable, this.Coefficient_A, this.Coefficient_B, this.Coefficient_C, this.coefficient_theta, this.checkingNumbers);
        this.operationInterface.addSimplexTableau(newSimplexTableau);
    }


    //检测是否输入的是纯数字
    private boolean checkIsNumber(String str){
        boolean isNumber = true;
        int count = 0;
        for(char c : str.toCharArray()) {
            count++;
            if(c<'0' || c>'9') {
                if(c == '-' && count == 1 && str.length() > 1) {
                    continue;
                }
                isNumber = false;
            }
        }
        return isNumber;
    }

    //检测是否输入的是纯数字或分数
    private boolean checkIsStringOfCommonFraction(String str) {
        boolean isStringOfCommonFraction = true;
        int numberOfSlash = 0;
        int count = 0;
        for(char c : str.toCharArray()) {
            count++;
            if(c == '-' && count == 1) {
                continue;
            }
            if(c == '/' && count != 1) {
                numberOfSlash++;
                continue;
            }
            if((c<'0' || c>'9')) {
                isStringOfCommonFraction = false;
                break;
            }
        }
        if(numberOfSlash > 1) {
            isStringOfCommonFraction = false;
        }
        return isStringOfCommonFraction;
    }


    //检测是否未输入
    private boolean checkIsNullString(String str){
        boolean isNull = false;
        if(str.equals("")) {
            isNull = true;
        }

        return isNull;
    }
    public static void main(String[] args) {
        new Console();
    }
}
